#include <Timer.h>
#include "pingpong.h"
module pingpongC
{
	uses interface Boot;
	uses interface Leds;

	uses interface Timer < TMilli > as Timer0;
	uses interface Timer < TMilli > as Alarm;

	//interfaces for radio tranceiver
	uses interface Packet as PacketRadio;
	uses interface AMPacket as AMPacketRadio;
	uses interface AMSend as AMSendRadio;
	uses interface SplitControl as AMControlRadio;
	uses interface Receive as ReceiveRadio;

	//interface for serial tranmission
	uses interface SplitControl as ControlSerial;
    uses interface AMSend as AMSendSerial;
   	uses interface Packet as PacketSerial;
	uses interface AMPacket as AMPacketSerial;
	uses interface Receive as ReceiveSerial;

}
implementation
{
	//init variables
	uint16_t counter = 0;
	bool haveball = TRUE;
	bool RadioBusy = FALSE;
	bool SerialBusy;
	message_t ball;
	uint16_t time=0;//time for each pingpong
	uint16_t timeStart=0;
	uint16_t timeStop=0;

	//booted: call serial start, call Alarm start
	event void Boot.booted ()
	{
		dbg ("Boot", "Boot execute\n");
		//after booted: start Control
		call ControlSerial.start();
		call Alarm.startPeriodic(TIMER_PERIODIC_MILLI);
	}
	
	
	//ControlSerial start done: call ControlRadio start
	event void ControlSerial.startDone(error_t err) 
	{
		if (err == SUCCESS) 
		{
			dbg ("ControlSerial", "ControlSerial Started\n");
			call AMControlRadio.start ();
		}
	}

	//AMcontrolRadio start done: call set timer
	event void AMControlRadio.startDone (error_t err)
	{
		if (err == SUCCESS)
		{
			dbg ("AMControlRadio", "AMControlRadio is started with SUCCESS\n");
			call Timer0.startOneShot(1);
		}
		else
		{
			dbg ("AMControlRadio", "AMControlRadio start is FAILURE\n");
			call AMControlRadio.start ();
		}
	}

	//timer fired: Counter++, send ball through radio if have ball
	event void Timer0.fired ()
	{
		dbg("Timer0","Timer fired\n");
		
		if (haveball) 
		{
			counter++;
			if (!RadioBusy)
			{
				pingpongMsg *messagePacked = (pingpongMsg *) (call PacketRadio.getPayload (&ball, NULL));
				dbg ("Timer0", "Radio Not busy\n");
				messagePacked->nodeid = TOS_NODE_ID;
				messagePacked->counter = counter;
				messagePacked->time = time;
				if (call AMSendRadio.send (AM_BROADCAST_ADDR, &ball,sizeof (pingpongMsg)) == SUCCESS)
				//if AMsned can be used: set alarm (counting start when ping)
				{
					dbg ("AMSendRadio", "Send ball throught Radio\n");
					RadioBusy = TRUE;
					timeStart=call Alarm.getNow();
					dbg ("Timer0", "Alarm start=%i\n",timeStart);
				}
			}else
			{
				call Timer0.startOneShot(TIMER_ONESHOT_MILLI);
			}

		}
	}
	//SendRadio Done: un lock the AMSendRadio, call SendSerial
	event void AMSendRadio.sendDone (message_t * msg, error_t error)
	{
		dbg ("AMSendRadio", "Send radio is done\n");
		if (&ball == msg)//test if the packet sent is the right one (AMsned maybe used by other component)
		{
			RadioBusy = FALSE;
			haveball=FALSE;
			if (!SerialBusy)
			{
				//pingpongMsg *messagePacked = (pingpongMsg *) (call PacketRadio.getPayload (&ball, NULL));
	      			pingpongMsg* messagePacked = (pingpongMsg*)call PacketSerial.getPayload(&ball, NULL);
				//pingpongMsg *messagePacked = (pingpongMsg *) (call PacketSerial.getPayload (&ball, NULL));
				dbg ("Timer0", "Serial not busy\n");
				messagePacked->nodeid = TOS_NODE_ID;
				messagePacked->counter = counter;
				messagePacked->time = time;
			
				if (call AMSendSerial.send(AM_BROADCAST_ADDR, &ball, sizeof(pingpongMsg)) == SUCCESS) 
					{
						dbg ("Timer0", "Send ball throught serial\n");
						SerialBusy = TRUE;
	     				}else{dbg ("Timer0", " NOT send ball throught serial\n");}
			}
		}
	}

	event void AMSendSerial.sendDone(message_t* bufPtr, error_t error) 
	{
		SerialBusy = FALSE;
		dbg ("pingpongC", "Serial send done\n");

	}




	//ball receive: haveball=TRUE, update counter, take time Stop and calcule timepingpong
	event message_t *ReceiveRadio.receive (message_t * msg, void *payload, uint8_t len)
	{
		dbg ("ReceiveRadio", "Ball received\n");
		if (len == sizeof (pingpongMsg))//neu nhan duoc day du
		{
			pingpongMsg *messagePacked = (pingpongMsg *) payload;
			haveball=TRUE;
			counter= messagePacked->counter;
			call Leds.set(counter);
			dbg ("ReceiveRadio", "counter=%i\n",counter);
			call Timer0.startOneShot(TIMER_ONESHOT_MILLI);
			//when ball received: get the timeStop on alarm
			timeStop=call Alarm.getNow();
			dbg ("ReceiveRadio", "timeStop = %i\n",timeStop);
			if (timeStop<timeStart)
		{
			time= TIMER_PERIODIC_MILLI-timeStart+timeStop;
		}else{
			time = timeStop - timeStart;
		}
		dbg ("ReceiveRadio", "time do pingpong = %i\n",time);
	}
	return msg;
	}
	event message_t* ReceiveSerial.receive(message_t* bufPtr,void* payload, uint8_t len) 
	{
      	return bufPtr;
  	}
	event void ControlSerial.stopDone(error_t err) 
	{
		dbg ("AMControlRadio", "AMControlRadio stop is done\n");
	}


event void AMControlRadio.stopDone (error_t err)
	{
		dbg ("AMControlRadio", "AMControlRadio stop is done\n");
	}
event void Alarm.fired()
	{
		//call Alarm.startPeriodic(1000);
		dbg ("pingpongC", "Alarm fired\n");
	}
}
	


